package de.sane.product

import de.sane.math.Rational
import Rational._

case class Stock(values: Map[String, Rational] = Map.empty[String, Rational]) {

	require(values != null && !values.exists(a => a._2 < 0))

	def +(that: Stock): Stock = {
		apply((a,b) => a + b, new Rational(0))(that)
	}
	
	def apply(op: (Rational, Rational) => Rational, default: Rational)(that: Stock): Stock = {
		/*
		*	Function that creates a map with the keys of this.values and the result of op on values of this.values and 
		* 	corresponding values in that.values (the values with the same key) or default if there is no value for the key
		*/
		val func = (a: (String,Rational)) => (a._1, op(a._2, that.values.getOrElse(a._1, default)))
		/*
		*	Creates a new map by applying the function and adding all key/value pairs of that.values there was no key in this.values
		*/
		val newValues = values.map(func) ++ that.values.filter(a => this.values.get(a._1) == None)
		new Stock(Stock.valuesToMin(new Rational(0))(newValues))
	}
	
	def -(that: Stock): Stock = {
		apply((a,b) => a - b, new Rational(0))(that)
	}
	
	
	
}

object Stock {

	/**
	* 
	*/
	def valuesToMin(min: Rational)(values: Map[String, Rational]): Map[String, Rational] = {
		values.map(a => (a._1, if(a._2 < min) min else a._2))
	}
	
	def valuesToMax(max: Rational)(values: Map[String, Rational]): Map[String, Rational] = {
		values.map(a => (a._1, if(a._2 > max) max else a._2))
	}
	
	def clampValues(min: Rational, max: Rational)(values: Map[String, Rational]): Map[String, Rational] = {
		values.map(a => (a._1, if(a._2 > max) max else {if(a._2 < min) min else a._2}))
	}
	
	

}